package br.brpv.silvestrin.updater;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.*;
import android.net.Uri;
import android.os.*;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;

public class Updater extends Activity implements View.OnClickListener {
    /** Messenger for communicating with service. */
    Messenger mService = null;
    /** Flag indicating whether we have called bind on the service. */
    boolean mIsBound;
    private ArrayList<App> mApps = new ArrayList<App>();

    private LinearLayout appsButtonsLayout;
    private MenuItem refreshMenuItem;


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        appsButtonsLayout = (LinearLayout) findViewById(R.id.apps_buttons_layout);

        Intent intent = new Intent(this, UpdaterService.class);
        startService(intent);
        doBindUpdaterService();
    }

    @Override
    public void onClick(View view) {
        switch (view.getId()){
            //case R.id.update_vendas_app_button:
            //    sendMessageToUpdaterService(UpdaterService.MSG_UPDATE_APP, 0);
            //    break;
            default:
                if(view.getTag().getClass() == App.class) {
                    App app = (App)view.getTag();
                    new DownLoadAndInstallApp(app.getUrl()).execute();
                }
                break;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.general_menu, menu);

        refreshMenuItem =  menu.findItem(R.id.menu_refresh);
        refreshMenuItem.setActionView(R.layout.action_refresh_progress);

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_refresh:
                refresh();
                break;
        }
        return true;
    }


    private void refresh(){
        sendMessageToUpdaterService(UpdaterService.MSG_UPDATE_APP, 0);
        refreshMenuItem.setActionView(R.layout.action_refresh_progress);
    }

    private void sendMessageToUpdaterService(int messageId, int arg1){
        try {
            Message msg = Message.obtain(null,
                    messageId);
            msg.replyTo = mMessenger;
            msg.arg1=arg1;
            mService.send(msg);
        } catch (RemoteException e) {

        }
    }

    /**
     * Handler of incoming messages from service.
     */
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UpdaterService.MSG_UPDATE_CHECK_DONE:
                    handleUpdateCheckDone();
                    break;
                case UpdaterService.MSG_UPDATE_CHECK_ERRO:
                    handleUpdateCheckError();
                    break;

                default:
                    super.handleMessage(msg);
            }
        }
    }

    private void handleUpdateCheckError() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);

        builder.setMessage(R.string.fail_on_update)
                .setCancelable(false)
                .setNeutralButton(R.string.dialog_ok, new DialogInterface.OnClickListener() {

                    public void onClick(DialogInterface dialog, int which) {
                    }
                })
                .create()
                .show();
    }

    private void handleUpdateCheckDone() {
        refreshMenuItem.setActionView(null);
        mApps = UpdaterService.getmApps();
        appsButtonsLayout.removeAllViews();
        for(int i = 0; i < mApps.size(); i++){

            Button button = new Button(this);
            button.setTag(mApps.get(i));
            button.setText(mApps.get(i).getName() + " " + mApps.get(i).getVersioname());
            button.setOnClickListener(this);
            button.setEnabled(!mApps.get(i).isUptodate());
            appsButtonsLayout.addView(button);
        }
    }

    /**
     * Target we publish for clients to send messages to IncomingHandler.
     */
    final Messenger mMessenger = new Messenger(new IncomingHandler());

    /**
     * Class for interacting with the main interface of the service.
     */
    private ServiceConnection mConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className,
                                       IBinder service) {

            mService = new Messenger(service);

            // We want to monitor the service for as long as we are
            // connected to it.
            try {
                Message msg = Message.obtain(null,
                        UpdaterService.MSG_REGISTER_CLIENT);
                msg.replyTo = mMessenger;
                mService.send(msg);

                // Give it some value as an example.
                msg = Message.obtain(null,
                        UpdaterService.MSG_SET_VALUE, this.hashCode(), 0);
                mService.send(msg);
            } catch (RemoteException e) {

            }

        }

        public void onServiceDisconnected(ComponentName className) {
            // This is called when the connection with the service has been
            // unexpectedly disconnected -- that is, its process crashed.
            mService = null;
        }
    };

    void doBindUpdaterService() {
        // Establish a connection with the service.  We use an explicit
        // class name because there is no reason to be able to let other
        // applications replace our component.
        bindService(new Intent(this, UpdaterService.class), mConnection, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }

    void doUnbindUpdaterService() {
        if (mIsBound) {
            // If we have received the service, and hence registered with
            // it, then now is the time to unregister.
            if (mService != null) {
                try {
                    Message msg = Message.obtain(null,
                            UpdaterService.MSG_UNREGISTER_CLIENT);
                    msg.replyTo = mMessenger;
                    mService.send(msg);
                } catch (RemoteException e) {

                }
            }

            // Detach our existing connection.
            unbindService(mConnection);
            mIsBound = false;
        }
    }

    @Override
    protected void onDestroy() {
        doUnbindUpdaterService();
        super.onDestroy();
    }

    private class DownLoadAndInstallApp extends AsyncTask<Void, Void, Void> {
        private String appURL;
        private String appName = "FileAux.apk";
        private ProgressDialog dialog;

        private DownLoadAndInstallApp(String appURL) {
            this.appURL = appURL;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog = new ProgressDialog(Updater.this);
            dialog.setMessage("Updating Application!");
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();
        }


        @Override
        protected Void doInBackground(Void... voids) {
            downloadApk(appURL, appName);

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            dialog.dismiss();
            installApk(appName);
            refresh();
        }

    }

    private void downloadApk(String appURL, String appName){
        try {
            URL url = new URL(appURL);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setUseCaches(false);
            urlConnection.setConnectTimeout(20*1000);
            urlConnection.setDoOutput(true);
            urlConnection.connect();

            File sdcard = Environment.getExternalStorageDirectory();
            File file = new File(sdcard, appName);

            FileOutputStream fileOutput = new FileOutputStream(file);
            InputStream inputStream = urlConnection.getInputStream();

            byte[] buffer = new byte[1024];
            int bufferLength = 0;

            while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
                fileOutput.write(buffer, 0, bufferLength);
            }
            fileOutput.close();
            //this.checkUnknownSourceEnability();
            //this.initiateInstallation();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void installApk(String appName){
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri uri = Uri.fromFile(new File("/sdcard/" + appName));
        intent.setDataAndType(uri, "application/vnd.android.package-archive");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

}
